LEMP 技术要点与踩坑指南

Linux + Nginx + MySQL + PHP  ·  Alibaba Cloud Linux 3
整体架构
用户请求 → Nginx (端口 80) → PHP-FPM (Unix Socket) → MySQL (端口 3306)
核心:Nginx 作为反向代理处理静态文件,PHP 请求转发给 PHP-FPM,动态内容通过 MySQL 存取数据。
Nginx 配置要点

1. server_name 与默认站点

server {
    listen 80;
    server_name example.com;
    ...
}

踩坑 server_name _; 不是通配符或 catch-all。Nginx 的默认站点由以下规则决定:

  • 标记为 listen 80 default_server 的站点是默认站点
  • 如果没有标记 default_server,则第一个加载的 server block 成为默认站点

宝塔面板中文件按字母序加载,phpfpm_status.conf 排在前面就成了默认站点,导致未匹配域名的请求都走到它那里返回欢迎页。

正确做法listen 80 default_server; 明确指定默认站点,或确保域名能精确匹配 server_name

2. PHP 解析配置

location ~ [^/]\.php(/|$) {
    try_files $uri =404;
    fastcgi_pass  unix:/tmp/php-cgi-82.sock;
    fastcgi_index index.php;
    include fastcgi.conf;
}

要点

  • try_files $uri =404 是安全必备,防止 PHP 路径穿越漏洞
  • 使用 Unix Socket(unix:/tmp/php-cgi-82.sock)比 TCP(127.0.0.1:9000)性能更好
  • 如果使用宝塔面板,用 include enable-php-82.conf; 一行即可,不要手写 location

3. Nginx 配置修改后必须做的事

# 第一步:语法检查
nginx -t

# 第二步:平滑重载(不断服务)
nginx -s reload

踩坑 改完配置不重载,不会生效。重启(restart)会短暂断连,尽量用 reload。

PHP-FPM 配置要点

1. 进程管理策略

pm = ondemand       # 按需启动子进程
pm.max_children = 30
模式说明适用场景
static固定进程数高流量、内存充足的服务器
dynamic动态调整流量波动大
ondemand有请求才启动低流量、节省内存

宝塔默认用 ondemand,低流量时很省内存,但首次请求会略慢。

2. Socket 通信

listen = /tmp/php-cgi-82.sock
listen.owner = www
listen.group = www
listen.mode = 0600

踩坑 Socket 文件权限必须与 Nginx worker 进程用户一致,否则返回 502 Bad Gateway。这里双方都用 www 用户。

3. php.ini 关键参数

max_execution_time = 300       # 最大执行时间(秒)
memory_limit = 128M            # 单脚本内存上限
upload_max_filesize = 50M      # 上传文件大小
post_max_size = 50M            # POST 数据大小

修改后重启 PHP-FPM:

kill -USR2 $(cat /www/server/php/82/var/run/php-fpm.pid)
MySQL 配置要点

1. 数据目录与 my.cnf

datadir = /www/server/data
port = 3306
socket = /tmp/mysql.sock

踩坑 宝塔安装的 MySQL 数据目录在 /www/server/data,不在标准路径。如果重装系统或迁移,要先备份这个目录。

2. 启动方式

宝塔的 MySQL 用 SysV init 脚本管理:

/etc/init.d/mysqld start|stop|restart
chkconfig mysqld on   # 设置开机自启

踩坑 宝塔的 mysql 包名是 bt-mysql57,不是标准的 mysql-server。用 yum install mysql 会装错。如果找不到 mysqld 二进制,检查 /www/server/mysql/bin/mysqld

3. 密码重置

/www/server/panel/pyenv/bin/python /www/server/panel/tools.py root 新密码

MySQL root 密码存储在宝塔面板 SQLite 数据库的 config 表中(mysql_root 字段)。

常见坑点汇总
#现象原因与解决
1PHP 文件 404访问 .php 文件返回 404Nginx 的 try_files 找不到文件,检查 root 路径和站点目录权限
2外部 IP 访问到默认页公网访问显示"没有找到站点"默认 server block 不对,用 default_server 指定
3502 Bad GatewayPHP 页面报 502PHP-FPM 未运行或 socket 权限不对,检查进程和 php-fpm.sock
4MySQL 连不上Can't connect to MySQL serverMySQL 未启动 (check /etc/init.d/mysqld start) 或端口被防火墙阻挡
5文件上传失败大文件上传到一半断了检查 php.ini 中的 upload_max_filesize 和 post_max_size,以及 Nginx 的 client_max_body_size
6修改配置不生效改了 nginx.conf 但没变化没有执行 nginx -s reload
7宝塔面板端口冲突面板打不开宝塔用 8888 端口,Nginx 用 888 作为 phpMyAdmin 端口,确保安全组放行
8磁盘空间暴涨日志文件越来越大日志在 /www/wwwlogs/,定期清理或用 logrotate 做轮转
安全建议
  1. 禁止 root 远程登录 MySQL — 创建专用数据库用户
    CREATE USER 'myuser'@'localhost' IDENTIFIED BY 'password';
    GRANT ALL PRIVILEGES ON mydb.* TO 'myuser'@'localhost';
    
  2. 限制 phpMyAdmin 访问 — 只允许白名单 IP
    allow 你的IP;
    deny all;
    
  3. 隐藏 Nginx 版本号server_tokens off;(宝塔默认已开启)
  4. 文件权限:站点文件所有者为 www 用户,不要用 777
  5. 定期更新yum update(阿里云 Linux 基于 CentOS 8)